package com.rays.gank.delegate

import android.app.Activity
import android.app.Dialog
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.viewbinding.ViewBinding
import com.rays.gank.ext.logD
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

/**
 * Created by Rays on 2021/1/24.
 */

inline fun <reified VB : ViewBinding> Activity.viewBinding() = lazy {
    val content = findViewById<ViewGroup>(android.R.id.content)
    val root = if (content.childCount == 1) content.getChildAt(0) else content
    "$content $root".logD()
    VB::class.java.getMethod("bind", View::class.java).invoke(null, root) as VB
//    inflateViewBinding<VB>(layoutInflater).apply { setContentView(root) }
}

inline fun <reified VB : ViewBinding> Dialog.viewBinding() = lazy {
    inflateViewBinding<VB>(layoutInflater).apply { setContentView(root) }
}

//@Suppress("UNCHECKED_CAST")
inline fun <reified VB : ViewBinding> inflateViewBinding(layoutInflater: LayoutInflater): VB =
    VB::class.java.getMethod("inflate", LayoutInflater::class.java)
        .invoke(null, layoutInflater) as VB

inline fun <reified VB : ViewBinding> Fragment.viewBinding() =
    FragmentBindingDelegate(VB::class.java)

class FragmentBindingDelegate<VB : ViewBinding>(private val clazz: Class<VB>) :
    ReadOnlyProperty<Fragment, VB> {

    private var isInitialized = false
    private var _binding: VB? = null
    private val binding: VB get() = _binding!!

    override fun getValue(thisRef: Fragment, property: KProperty<*>): VB {
        if (!isInitialized) {
            isInitialized = true
            thisRef.viewLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
                @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
                fun onDestroyView() {
                    _binding = null
                }
            })
            @Suppress("UNCHECKED_CAST")
            _binding =
                clazz.getMethod("bind", View::class.java).invoke(null, thisRef.requireView()) as VB
        }
        return binding
    }
}
